package com.boardour.socket.client;

import android.util.Log;

import com.boardour.socket.foo.constants.TCPConstants;
import com.boardour.socket.listener.OnReceivedJsonListener;

import net.qiujuer.library.clink.box.BytesSendPacket;
import net.qiujuer.library.clink.core.Connector;
import net.qiujuer.library.clink.core.IoContext;
import net.qiujuer.library.clink.impl.IoSelectorProvider;
import net.qiujuer.library.clink.impl.SchedulerImpl;
import net.qiujuer.library.clink.utils.CloseUtils;

import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

public class TCPClientPresenter implements Runnable, TCPClient.ConnectorStatusListener, TCPClient.MessageArrivedListener, OnReceivedJsonListener {

    public static final String TAG = "ClientPresenter";
    private TCPClient mClient;
    private InetAddress address;
    private AtomicBoolean isInit = new AtomicBoolean(false);
    private volatile boolean isFinish;
    private AtomicBoolean isConnect = new AtomicBoolean(false);
    private OnReceivedJsonListener onReceivedJsonListener;
    private int port = -1;
    private String ip;

    // 1. 初始化
    // 2. 连接服务器
    private boolean init() {
        if (isInit.get()) {
            return true;
        }
        if (isInit.compareAndSet(false, true)) {
            try {
                IoContext.setup()
                        .ioProvider(new IoSelectorProvider())
                        .scheduler(new SchedulerImpl(4))
                        .start();
            } catch (Exception e) {
                Log.e(TAG, "初始化失败");
                isInit.set(false);
                // 销毁
                close();
                // 失败
            }
        }

        return isInit.get();
    }

    public void connect(InetAddress address) {
        connect(address, TCPConstants.PORT_SERVER);
    }

    // 2. 连接服务器
    public void connect(InetAddress address, int port) {
        this.port = port;
        if (address == null) {
            return;
        }
        if (this.address != null && !this.address.equals(address)) {
            close();
        }
        if (this.isConnect.compareAndSet(false, true)) {
            this.address = address;
            isFinish = false;
            ExecutorService executorService = Executors.newSingleThreadExecutor();
            executorService.execute(this);
        }
    }

    public void connect(String ip, int port) {
        this.port = port;
        if (ip == null) {
            return;
        }
        if (this.ip != null && !this.ip.equals(ip)) {
            close();
        }
        if (this.isConnect.compareAndSet(false, true)) {
            this.ip = ip;
            isFinish = false;
            ExecutorService executorService = Executors.newSingleThreadExecutor();
            executorService.execute(this);
        }
    }

    @Override
    public void run() {
        // 在这里初始化
        if (!init()) {
            return;
        }
        try {
            if (address != null) {
                mClient = new TCPClient(address.getHostName(), port);
                Log.e(TAG, "client:" + address.getHostName());
            } else {
                mClient = new TCPClient(ip, port);
            }
            mClient.setConnectorStatusListener(TCPClientPresenter.this);
            mClient.setOnReceivedJsonListener(this);
            isFinish = true;
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "ConnectTask Exception:" + e.getMessage());
            close();
        }
    }

    /**
     * 发送Json数据
     */
    public void send(String json) {
        if (!isFinish) {
            return;
        }
        mClient.send(json);
    }

    /**
     * 发送数据
     */
    public void send(int trackIndex, byte[] data, long presentationTimeUs) {
        if (!isFinish) {
            return;
        }
        delivery(trackIndex, data, presentationTimeUs);
    }

    private void delivery(int trackIndex, byte[] data, long presentationTimeUs) {
        // 添加个阀值
        // 1. 先写，然后发送直流包
        try {
            // 组装数据
            // trackIndex + presentationTimeUs + length + data
            // 4 + 8 + 4 + length
            int size = 16 + data.length;
            ByteBuffer buffer = ByteBuffer.allocate(size);
            buffer.putInt(trackIndex);
            buffer.putLong(presentationTimeUs);
            buffer.putInt(data.length);
            buffer.put(data);
            // 写数据
            BytesSendPacket packet = new BytesSendPacket(buffer.array());
            mClient.send(packet);
        } catch (Exception e) {
            Log.e("TAG", "send e" + e.getMessage());
            e.printStackTrace();
        }
    }

    public void close() {
        Log.e("TAG", "client close");
        if (isConnect.compareAndSet(true, false)) {
            CloseUtils.close(mClient);
            mClient = null;
            address = null;
            // 清理缓冲区
            isFinish = false;
        }

    }


    @Override
    public void onConnectorClosed(Connector connector) {
        close();
    }

    @Override
    public void onNewMessageArrived(ConnectorInfo info) {
        Log.e(TAG, info.toString());
    }

    @Override
    public void onReceivedJson(String json, SocketChannel channel) {
        if (this.onReceivedJsonListener != null) {
            this.onReceivedJsonListener.onReceivedJson(json, channel);
        }
    }

    public void setOnReceivedJsonListener(OnReceivedJsonListener onReceivedJsonListener) {
        this.onReceivedJsonListener = onReceivedJsonListener;
    }
}
